package storage_processor

import (
	"encoding/binary"
	"go-iot-gateway/internal/apk/binarys"
	"go-iot-gateway/internal/apk/maths"
	"go-iot-gateway/internal/conf_table"
	conf_table_define "go-iot-gateway/internal/conf_table/define"
	"go-iot-gateway/internal/logger"
	storage_define "go-iot-gateway/internal/storage/define"
)

// 根据点表，值直接计算
func DirectProcessorByTag(val storage_define.ValObject) storage_define.ValObject {
	//todo 偏移计算
	//todo 系数计算

	// 获取的tagInfo 不包含转发
	tagInfo, err := conf_table.FindTagByName(val.TagName())

	if tagInfo == nil || err != nil {
		logger.Storage().Warn("根据标签名称查询标签不存在 ", val.TagName())
		return val
	}

	if !needProcess(val, tagInfo) {
		return val
	}

	if float64Val, ok := val.(*storage_define.Float64Val); ok {
		return processFloat64Val(float64Val, tagInfo)
	} else if uint64Val, ok := val.(*storage_define.Uint64Val); ok {
		return processUint64Val(uint64Val, tagInfo)
	} else if int64Val, ok := val.(*storage_define.Int64Val); ok {
		return processInt64Val(int64Val, tagInfo)
	}

	return val
}

func toByteArr(val *storage_define.Int64Val, tagInfo *conf_table_define.TagInfo) []byte {
	bytes := make([]byte, 8)
	binary.BigEndian.PutUint64(bytes, uint64(val.Int64Val()))

	return bytes[8-tagInfo.ByteSize():]
}

func processUint64Val(val *storage_define.Uint64Val, tagInfo *conf_table_define.TagInfo) storage_define.ValObject {

	//处理按位取值
	uintVal := val.Uint64Val()

	if tagInfo.EnableBit() {
		bytes := make([]byte, 8)
		binary.BigEndian.PutUint64(bytes, val.Uint64Val())
		arr := bytes[8-tagInfo.ByteSize():]
		bit := binarys.TurnBit(arr, uint64(tagInfo.Start_bit), uint64(tagInfo.End_bit))
		uintVal = bit
	}

	//todo 偏移计算

	//todo 取反

	if tagInfo.Tag_K == 1 {
		val.SetUint64Val(uintVal)
		return val
	}

	//系数处理
	oriVal := float64(uintVal)
	oriVal = maths.RoundPlaces(oriVal*float64(tagInfo.Tag_K), 5)

	return storage_define.NewFloat64Val(val.TagName(), oriVal, val.Ts(), val.Qos())
}

func processInt64Val(val *storage_define.Int64Val, tagInfo *conf_table_define.TagInfo) storage_define.ValObject {

	//处理按位取值
	intVal := val.Int64Val()

	if tagInfo.EnableBit() {
		arr := toByteArr(val, tagInfo)
		bit := binarys.TurnBit(arr, uint64(tagInfo.Start_bit), uint64(tagInfo.End_bit))
		intVal = int64(bit)
	}

	//todo 偏移计算

	//todo 取反

	if tagInfo.Tag_K == 1 {
		val.SetInt64Val(intVal)
		return val
	}

	//系数处理
	oriVal := float64(intVal)
	oriVal = maths.RoundPlaces(oriVal*float64(tagInfo.Tag_K), 5)

	return storage_define.NewFloat64Val(val.TagName(), oriVal, val.Ts(), val.Qos())
}

func processFloat64Val(val *storage_define.Float64Val, tagInfo *conf_table_define.TagInfo) storage_define.ValObject {
	oriVal := val.Float64Val()

	if tagInfo.Tag_K != 1 {
		oriVal = maths.RoundPlaces(oriVal*float64(tagInfo.Tag_K), 5)
	}

	val.SetFloat64Val(oriVal)

	return val
}

// 根据标签判断是否要处理
func needProcess(val storage_define.ValObject, tagInfo *conf_table_define.TagInfo) bool {
	if tagInfo.IsYk() || tagInfo.IsYt() {
		return false
	}
	//空值 ， 字符串不处理
	if _, ok := val.(*storage_define.NilVal); ok {
		return false
	}
	if _, ok := val.(*storage_define.StringVal); ok {
		return false
	}

	return true
}
